package com.nhc.activity_fragment;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;

import com.astrob.activitys.GPSProvider;
import com.astrob.model.LonLat;
import com.astrob.naviframe.Start;
import com.astrob.nhcmap.R;
import com.astrob.util.SysUtils;
import com.astrob.util.Utils;
import com.nhc.database.dbmodel.SystemAllInfo;
import com.nhc.database.manager.SystemCenter;
import com.nhc.model.CompassDatainfo;
import com.nhc.model.CourseInfo;
import com.nhc.model.TripDataFileHandle;
import com.nhc.model.TripDatainfo;
import com.nhc.model.TripItem;
import com.nhc.view.CompassView;
import com.nhc.view.TripItemViewLayout;

import zuo.biao.library.base.BaseFragment;
import zuo.biao.library.ui.AlertDialog;

//MIUI指南针社区开源版
//https://github.com/MiCode/Compass#readme

//校准算法
//http://home.earthlink.net/~david.schultz/rnd/tracker/cal.c

public class CompassFragment extends BaseFragment implements View.OnClickListener {
    private final String TAG = "CompassFragment";

    //与Activity通信<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    /**
     * 创建一个Fragment实例
     *
     * @return
     */
    public static CompassFragment createInstance() {
        return new CompassFragment();
    }

    //与Activity通信>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        if (SysUtils.getInstance().is240x320) {
            setContentView(R.layout.compass_fragment_240x320);
        } else {
            setContentView(R.layout.compass_fragment);
        }


        //功能归类分区方法，必须调用<<<<<<<<<<
        initView();
        initData();
        initEvent();
        //功能归类分区方法，必须调用>>>>>>>>>>

        return view;//返回值必须为view
    }

    //UI显示区(操作UI，但不存在数据获取或处理代码，也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    private TripItemViewLayout tripiemview[] = new TripItemViewLayout[4];
    private int[] LL_CTRL = {R.id.tripiemview_0, R.id.tripiemview_1, R.id.tripiemview_2, R.id.tripiemview_3};
    private CompassView mPointer;
    private CompassView mPointer2;

    private AnimationDrawable mAnimationDrawable = null;
    private View view_calibration;
    int _calibration = -1;

    @Override
    public void initView() {//必须在onCreateView方法内调用
        for (int i = 0; i < LL_CTRL.length; i++) {
            tripiemview[i] = (TripItemViewLayout) findViewById(LL_CTRL[i]);
        }
        mPointer = (CompassView) findViewById(R.id.compass_pointer);
        mPointer2 = (CompassView) findViewById(R.id.compass_pointer2);
        mPointer2.setVisibility(View.GONE);

        view_calibration = (View)findViewById(R.id.view_calibration);
        mAnimationDrawable = new AnimationDrawable();
        for(int i = 1; i <= 7; i++){
            int id = getResources().getIdentifier("calibration"+ i, "drawable", getContext().getPackageName());
            mAnimationDrawable.addFrame(getResources().getDrawable(id), 100);
        }
        mAnimationDrawable.setOneShot(false);
        view_calibration.setBackgroundDrawable(mAnimationDrawable);

        if (needCalibration()) {
            doCalibration();
        }

    }

    void doCalibration() {
        _calibration = 0;
        mAnimationDrawable.start();
        view_calibration.setVisibility(View.VISIBLE);
        setCalibration();
    }

    void calibrationOver() {
        _calibration = -1;
        mAnimationDrawable.stop();
        view_calibration.setVisibility(View.GONE);
    }

    private static final String Calibration = "Calibration";

    private boolean needCalibration() {
        SystemAllInfo sInfo = SystemCenter.getInstance().getSysInfo(Calibration);
        if (sInfo == null) {
            return true;
        }
        return false;
    }

    private void setCalibration() {
        SystemAllInfo sInfo = SystemCenter.getInstance().getSysInfo(Calibration);
        if (sInfo == null) {
            sInfo = new SystemAllInfo(null, Calibration, "T");
            SystemCenter.getInstance().saveSysInfo(sInfo);
        }
    }

    //UI显示区(操作UI，但不存在数据获取或处理代码，也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


    //Data数据区(存在数据获取或处理代码，但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    private CompassDatainfo compassDatainfo = new CompassDatainfo();
    private TripDatainfo mTripDatainfo;

    private final float MAX_ROATE_DEGREE = 1.0f;
    private SensorManager mSensorManager;
    private float mDirection;
    private float mTargetDirection;
    private AccelerateInterpolator mInterpolator;
    protected final Handler mHandler = new Handler();
    private boolean mStopDrawing;

    //记录rotationMatrix矩阵值
    private float[] r = new float[9];
    //记录通过getOrientation()计算出来的方位横滚俯仰值
    private float[] values = new float[3];
    private float[] gravity = null;
    private float[] geomagnetic = null;


    private GPSProvider mGpsProvider;

    @Override
    public void initData() {//必须在onCreateView方法内调用
        mDirection = 0.0f;
        mTargetDirection = 0.0f;
        mInterpolator = new AccelerateInterpolator();
        mStopDrawing = true;

        mGpsProvider = GPSProvider.getInstance();

        mTripDatainfo = TripDataFileHandle.getInstance().mTripDatainfo;

        refreshData();
    }

    private void refreshData() {

        if (_calibration >= 0) {
            _calibration++;
            if (_calibration > 50) {
                calibrationOver();
            }
        }

        String strHX = "-----";
        String strFW = "-----";

        for (int i = 0; i < LL_CTRL.length; i++) {
            int index = mTripDatainfo.DATATYPE_INDEXS_COMPASS[i];
            if (index < 0 || index >= mTripDatainfo.DATATYPE_NAMES.length) {
                continue;
            }
            String name = mTripDatainfo.DATATYPE_NAMES[index];
            String CC[] = mTripDatainfo.getInfoForCompass(index);
            //4, 17
            if (index == 17) {
                tripiemview[i].bindView(new TripItem(getString(R.string.dqmb), compassDatainfo.getAzimuthstr(), " "));
            } else if (index == 16) {
                tripiemview[i].bindView(new TripItem(name, Utils.getDirName(compassDatainfo.getAzimuth()), " "));
            } else {
                tripiemview[i].bindView(new TripItem(name, CC[0], CC[1]));
            }

        }

//        if (Start.getInstance().isHavePath()) {
//            LonLat carLL = SysUtils.getInstance().getLL();
//            double lon = Start.getInstance().MapKit().mNavDest[0].pos.lon;
//            double lat = Start.getInstance().MapKit().mNavDest[0].pos.lat;
//            strFW = Start.getInstance().MapKit().getDirection(carLL, new LonLat(lon, lat));
//
//            double lon0 = Start.getInstance().MapKit().mNavStart.pos.lon;
//            double lat0 = Start.getInstance().MapKit().mNavStart.pos.lat;
//            LonLat startLL = new LonLat(lon0, lat0);
//            strHX = Start.getInstance().MapKit().getDirection(startLL, new LonLat(lon, lat));
//        }
//
//        String VEL[] = SysUtils.getInstance().getVelStr(mGpsProvider.getSpeed());
//        tripiemview_0.bindView(new TripItem(getString(R.string.dqvel), VEL[0], VEL[1]));
//        tripiemview_1.bindView(new TripItem(getString(R.string.hangxian), strHX, " "));
//        tripiemview_2.bindView(new TripItem(getString(R.string.fangwei), strFW, " "));
//        tripiemview_3.bindView(new TripItem(getString(R.string.dqmb), compassDatainfo.getAzimuthstr(), " "));
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (gravity != null && geomagnetic != null) {
                if (SensorManager.getRotationMatrix(r, null, gravity, geomagnetic)) {
                    SensorManager.getOrientation(r, values);
                    float degree = (float) ((360f + values[0] * 180f / Math.PI) % 360);
//                    Log.i(TAG, "计算出来的方位角＝" + degree);

                    float dir = degree;
                    if (GPSProvider.getInstance().getSpeed() * 3.6 > CourseInfo.getInstance().getLpvel()) {
                        dir = GPSProvider.getInstance().getDirection();
                    }
                    float direction = dir * -1.0f;
                    mTargetDirection = normalizeDegree(direction);
                }
            }
        }
    };

    protected Runnable mCompassViewUpdater = new Runnable() {
        @Override
        public void run() {
            if (mPointer != null && !mStopDrawing) {
                if (mDirection != mTargetDirection) {

                    // calculate the short routine
                    float to = mTargetDirection;
                    if (to - mDirection > 180) {
                        to -= 360;
                    } else if (to - mDirection < -180) {
                        to += 360;
                    }

                    // limit the max speed to MAX_ROTATE_DEGREE
                    float distance = to - mDirection;
                    if (Math.abs(distance) > MAX_ROATE_DEGREE) {
                        distance = distance > 0 ? MAX_ROATE_DEGREE : (-1.0f * MAX_ROATE_DEGREE);
                    }

                    // need to slow down if the distance is short
                    mDirection = normalizeDegree(mDirection
                            + ((to - mDirection) * mInterpolator.getInterpolation(Math
                            .abs(distance) > MAX_ROATE_DEGREE ? 0.4f : 0.3f)));
                    mPointer.updateDirection(mDirection);
                    if (Start.getInstance().isHavePath()) {
                        mPointer2.setVisibility(View.VISIBLE);

                        //得到航向  car->B
                        LonLat carLL = SysUtils.getInstance().getLL();
                        carLL = Utils.wgs84togcj02(carLL.GetLon(), carLL.GetLat());//Utils GPS to 火星坐标
                        double lon = Start.getInstance().MapKit().mNavDest[0].pos.lon;
                        double lat = Start.getInstance().MapKit().mNavDest[0].pos.lat;
                        double dir2B = Start.getInstance().MapKit().getDirection3(carLL, new LonLat(lon, lat));

                        mPointer2.updateDirection((float) (mDirection + dir2B));

                    } else {
                        mPointer2.setVisibility(View.GONE);
                    }
                }

                updateDirection();
                refreshData();

                mHandler.postDelayed(mCompassViewUpdater, 20);
            }
        }
    };

    //Data数据区(存在数据获取或处理代码，但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


    //Event事件区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    @Override
    public void initEvent() {//必须在onCreateView方法内调用
        for (int i = 0; i < tripiemview.length; i++) {
            tripiemview[i].setOnClickListener(this);
        }

        initServices();
    }
//    https://blog.csdn.net/wukong1981/article/details/39967699
    private void initServices() {
        // sensor manager
        mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);

    }

    //系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    @Override
    public void onClick(View v) {//直接调用不会显示v被点击效果
        for (int i = 0; i < LL_CTRL.length; i++) {
            if (v.getId() == LL_CTRL[i]) {
                toActivity(ChangeDataTypeActivity.createIntent(getContext(), mTripDatainfo.DATATYPE_INDEXS_COMPASS[i]), i);
                break;
            }
        }
    }

    boolean _isFirst = true;

    public void setFoucseCtrl() {
        if (!_isFirst) {
            return;
        }

        _isFirst = false;

        for (int i = 0; i < LL_CTRL.length; i++) {
            findViewById(LL_CTRL[i]).setFocusable(true);
        }

        findViewById(LL_CTRL[0]).requestFocus();
    }

    //类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    @Override
    public void onResume() {
        super.onResume();

        Sensor gsensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        Sensor msensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        mSensorManager.registerListener(mOrientationSensorEventListener, gsensor, SensorManager.SENSOR_DELAY_GAME);
        mSensorManager.registerListener(mOrientationSensorEventListener, msensor, SensorManager.SENSOR_DELAY_GAME);

        mStopDrawing = false;
        mHandler.postDelayed(mCompassViewUpdater, 20);
    }

    @Override
    public void onPause() {
        super.onPause();
        mStopDrawing = true;
        mSensorManager.unregisterListener(mOrientationSensorEventListener);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    private void updateDirection() {
        float direction = normalizeDegree(mTargetDirection * -1.0f);
        if (direction > 22.5f && direction < 157.5f) {
            // east
            compassDatainfo.setDirname("东");
        } else if (direction > 202.5f && direction < 337.5f) {
            // west
            compassDatainfo.setDirname("西");
        }

        if (direction > 112.5f && direction < 247.5f) {
            // south
            compassDatainfo.setDirname("南");
        } else if (direction < 67.5 || direction > 292.5f) {
            // north
            compassDatainfo.setDirname("北");
        }

        compassDatainfo.setAzimuth((int) direction);
    }

    private void updateLocation(Location location) {
        if (location == null) {
//            mLocationTextView.setText(R.string.getting_location);
            showShortToast(R.string.getting_location);
        } else {
            StringBuilder sb = new StringBuilder();
            double latitude = location.getLatitude();
            double longitude = location.getLongitude();
            compassDatainfo.setCurrentvel(location.getSpeed() * 3.6f);

            if (latitude >= 0.0f) {
                sb.append(getString(R.string.location_north, getLocationString(latitude)));
            } else {
                sb.append(getString(R.string.location_south, getLocationString(-1.0 * latitude)));
            }

            sb.append("    ");

            if (longitude >= 0.0f) {
                sb.append(getString(R.string.location_east, getLocationString(longitude)));
            } else {
                sb.append(getString(R.string.location_west, getLocationString(-1.0 * longitude)));
            }

//            mLocationTextView.setText(sb.toString());
            showShortToast(sb.toString());
        }
    }

    private String getLocationString(double input) {
        int du = (int) input;
        int fen = (((int) ((input - du) * 3600))) / 60;
        int miao = (((int) ((input - du) * 3600))) % 60;
        return String.valueOf(du) + "°" + String.valueOf(fen) + "'" + String.valueOf(miao) + "\"";
    }

    private float[] mGData = new float[3];
    private float[] mMData = new float[3];
    private float[] mR = new float[16];
    private float[] mI = new float[16];
    private float[] mOrientation = new float[3];
    private int mCount;

//    https://blog.csdn.net/wukong1981/article/details/39967699
    private SensorEventListener mOrientationSensorEventListener = new SensorEventListener() {

        @Override
        public void onSensorChanged(SensorEvent event) {
//            switch (event.sensor.getType()) {
//                case Sensor.TYPE_ACCELEROMETER: //加速度传感器
//                    gravity = event.values;
//                    handler.sendEmptyMessage(0);
//                    break;
//                case Sensor.TYPE_MAGNETIC_FIELD://磁场传感器
//                    geomagnetic = event.values;
//                    handler.sendEmptyMessage(0);
//                    break;
//            }
            int type = event.sensor.getType();
            float[] data;
            if (type == Sensor.TYPE_ACCELEROMETER) {
                data = mGData;
            } else if (type == Sensor.TYPE_MAGNETIC_FIELD) {
                data = mMData;
            } else {
                // we should not be here.
                return;
            }
            for (int i = 0; i < 3; i++)
                data[i] = event.values[i];

//            if (!SensorManager.getRotationMatrix(mR, mI, mGData, mMData)) {
//                return;
//            }
            SensorManager.getRotationMatrix(mR, mI, mGData, mMData);

// some test code which will be used/cleaned up before we ship this.
//        SensorManager.remapCoordinateSystem(mR,
//                SensorManager.AXIS_X, SensorManager.AXIS_Z, mR);
//        SensorManager.remapCoordinateSystem(mR,
//                SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, mR);
            SensorManager.getOrientation(mR, mOrientation);
            float incl = SensorManager.getInclination(mI);

            if (mCount++ > 50) {
                final float rad2deg = (float) (180.0f / Math.PI);
                mCount = 0;
//                Log.d("Compass", "yaw: " + (int)(mOrientation[0]*rad2deg) +
//                        "  pitch: " + (int)(mOrientation[1]*rad2deg) +
//                        "  roll: " + (int)(mOrientation[2]*rad2deg) +
//                        "  incl: " + (int)(incl*rad2deg)
//                );

                float degree = (float) ((360f + mOrientation[0] * rad2deg) % 360);
                float dir = degree;
                if (CourseInfo.getInstance().isUseGpsdir(GPSProvider.getInstance().getSpeed() * 3.6f)) {
                    dir = GPSProvider.getInstance().getDirection();
                }
                float direction = dir * -1.0f;
                mTargetDirection = normalizeDegree(direction);
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
        }
    };

    private float normalizeDegree(float degree) {
        return (degree + 720) % 360;
    }

    //类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    //系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    //Event事件区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (RESULT_OK == resultCode) {
            refreshData();
        } else {
            if (requestCode >= 0 && requestCode < 8) {
                mTripDatainfo.DATATYPE_INDEXS_COMPASS[requestCode] = resultCode;
                TripDataFileHandle.getInstance().save();
                refreshData();
            }
        }
    }


}